home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-19 | 16.7 KB | 494 lines | [TEXT/CWIE] |
- #include "MoreStrings.h"
- #include "Exceptions.h"
-
- #include <AERegistry.h>
- #include <TextUtils.h>
-
-
-
-
- //========================================================================================
- // CLASS TString
- //========================================================================================
-
-
- TString::TString() :
- fStr(nil),
- fStringScript(smSystemScript),
- fStringLanguage(scriptDefLang),
- fActualSizeInBytes(0),
- fMaximumSizeInBytes(256),
- fStorageAllocatedInHeap(true)
- {
- fStr = new unsigned char[fMaximumSizeInBytes];
- fStr[0] = 0;
- }
-
- TString::TString(const TString& string) :
- fStr(nil),
- fStringScript(smSystemScript),
- fStringLanguage(scriptDefLang),
- fActualSizeInBytes(0),
- fMaximumSizeInBytes(string.StringLength()),
- fStorageAllocatedInHeap(true)
- {
- fStr = new unsigned char[fMaximumSizeInBytes];
- fStr[0] = 0;
-
- *this = string;
- }
-
- TString::TString(const TDescriptor& desc) :
- fStr(nil),
- fStringScript(smSystemScript),
- fStringLanguage(scriptDefLang),
- fActualSizeInBytes(0),
- fMaximumSizeInBytes(256),
- fStorageAllocatedInHeap(true)
- {
- fStr = new unsigned char[fMaximumSizeInBytes];
- fStr[0] = 0;
-
- *this = desc;
- }
-
- TString::TString(UInt32 maximumSize) :
- fStr(nil),
- fStringScript(smSystemScript),
- fStringLanguage(scriptDefLang),
- fActualSizeInBytes(0),
- fMaximumSizeInBytes(maximumSize),
- fStorageAllocatedInHeap(true)
- {
- fStr = new unsigned char[fMaximumSizeInBytes];
- fStr[0] = 0;
- }
-
- TString::TString(unsigned char* stringExternalStorage, UInt32 maximumSize, UInt32 currentSizeInBytes, ScriptCode stringScript, LangCode stringLanguage) :
- fStr(stringExternalStorage),
- fStringScript(stringScript),
- fStringLanguage(stringLanguage),
- fMaximumSizeInBytes(maximumSize),
- fStorageAllocatedInHeap(false)
- {
- this->SetLength(currentSizeInBytes);
- }
-
- TString::TString(unsigned char* stringExternalStorage) :
- fStr(stringExternalStorage),
- fStringScript(smSystemScript),
- fStringLanguage(scriptDefLang),
- fActualSizeInBytes(stringExternalStorage[0]),
- fMaximumSizeInBytes(256),
- fStorageAllocatedInHeap(false)
- {
- }
-
- TString::~TString()
- {
- if(fStorageAllocatedInHeap)
- delete fStr;
- }
-
-
- //----------------------------------------------------------------------------------------
- // TString::TDescriptor:
- //----------------------------------------------------------------------------------------
- TString::operator TDescriptor() const
- {
- TDescriptor result;
-
- //
- // If this string doesn't have any particular script code associated with it,
- // then build a typeChar descriptor. Otherwise, make a typeIntlText descriptor.
- //
- if(this->StringScript() == smSystemScript)
- {
- result.SetDescriptorData(TConstDataReference(typeChar, (char*)this->TextStart(), this->StringLength()));
- }
- else
- {
- SInt32 dataSize = this->StringLength() + (sizeof(ScriptCode) + sizeof(LangCode));
- struct IntlText* theIntlText = (struct IntlText*) new char[dataSize];
- theIntlText->theScriptCode = this->StringScript();
- theIntlText->theLangCode = this->StringLanguage();
- TUpdataDataReference updateReference(typeChar, &theIntlText->theText[0], 0, this->StringLength());
- updateReference.CopyFrom(TConstDataReference(typeChar, (char*)this->TextStart(), this->StringLength()));
-
- result.SetDescriptorData(updateReference);
- delete theIntlText;
- }
-
- return result;
- } // TString::operator TDescriptor
-
- //----------------------------------------------------------------------------------------
- // TString::operator=:
- //----------------------------------------------------------------------------------------
- TString& TString::operator=(const TString& rhs)
- {
- this->Replace(kStringStart, kStringEnd, rhs);
-
- return *this;
- } // TString::operator=
-
- //----------------------------------------------------------------------------------------
- // TString::operator=:
- //----------------------------------------------------------------------------------------
- TString& TString::operator=(const TDescriptor& desc)
- {
- if(desc.DescriptorType() == typeIntlText)
- {
- SInt32 dataSize = desc.DataSize();
- this->ExpandToFit(dataSize);
- struct IntlText* theIntlText = (struct IntlText*) new char[dataSize];
- TUpdataDataReference updateReference(typeIntlText, (char*)theIntlText, 0, dataSize);
- desc.GetDescriptorData(updateReference);
- SInt32 rawTextSize = updateReference.DataLength() - (sizeof(ScriptCode) + sizeof(LangCode));
-
- //
- // In addition to the string, we'll also get a header with
- // script and language code information in it stuck on the
- // beginning of our data.
- //
- TString theIntlString((unsigned char*)theIntlText->theText, rawTextSize, rawTextSize, theIntlText->theScriptCode, theIntlText->theLangCode);
- *this = theIntlString;
- delete theIntlText;
- }
- if(desc.DescriptorType() == typeChar)
- {
- SInt32 dataSize = desc.DataSize();
- this->ExpandToFit(dataSize);
- TUpdataDataReference updateReference(typeChar, (char*)this->TextStart(), this->StringLength(), this->MaximumSizeInBytes());
- desc.GetDescriptorData(updateReference);
- fStringScript = smSystemScript;
- fStringLanguage = scriptDefLang;
- this->SetLength(updateReference.DataLength());
- }
- else
- {
- OSErr err = noErr;
- TDescriptor coercedDescriptor = desc.AttemptToCoerce(typeIntlText, err);
- if(coercedDescriptor.DescriptorType() == typeIntlText)
- *this = coercedDescriptor;
- else
- {
- coercedDescriptor.Dispose();
- coercedDescriptor = desc.AttemptToCoerce(typeChar, err);
- if(coercedDescriptor.DescriptorType() == typeChar)
- *this = coercedDescriptor;
- }
- coercedDescriptor.Dispose();
- }
-
- return *this;
- } // TString::operator=
-
- //----------------------------------------------------------------------------------------
- // TString::SetLength:
- //----------------------------------------------------------------------------------------
- void TString::SetLength(UInt32 newLength)
- {
- fActualSizeInBytes = newLength;
- if(newLength < 255)
- fStr[0] = newLength;
- else
- fStr[0] = 255;
- } // TString::Length
-
- //----------------------------------------------------------------------------------------
- // TString::CorrectInternalLength:
- //----------------------------------------------------------------------------------------
- void TString::CorrectInternalLength() const
- {
- if(fStr[0] != 255)
- ((TString*)this)->fActualSizeInBytes = fStr[0];
- else if(fActualSizeInBytes < 255)
- ((TString*)this)->fActualSizeInBytes = 255;
- } // TString::Length
-
- //----------------------------------------------------------------------------------------
- // TString::Length:
- //----------------------------------------------------------------------------------------
- UInt32 TString::StringLength() const
- {
- this->CorrectInternalLength();
-
- return fActualSizeInBytes;
- } // TString::Length
-
- //----------------------------------------------------------------------------------------
- // TString::SizeInBytes:
- //----------------------------------------------------------------------------------------
- UInt32 TString::SizeInBytes() const
- {
- //
- // Add one for the length byte
- //
- return this->StringLength() + 1;
- } // TString::SizeInBytes
-
- //----------------------------------------------------------------------------------------
- // TString::MaximumSizeInBytes:
- //----------------------------------------------------------------------------------------
- UInt32 TString::MaximumSizeInBytes() const
- {
- return fMaximumSizeInBytes;
- } // TString::MaximumSizeInBytes
-
- //----------------------------------------------------------------------------------------
- // TString::Empty:
- //----------------------------------------------------------------------------------------
- Boolean TString::Empty() const
- {
- return (this->StringLength() == 0);
- } // TString::Empty
-
- //----------------------------------------------------------------------------------------
- // TString::ClearString:
- //----------------------------------------------------------------------------------------
- void TString::ClearString()
- {
- this->SetLength(0);
- } // TString::ClearString
-
- //----------------------------------------------------------------------------------------
- // TString::CompareStringOrder:
- //----------------------------------------------------------------------------------------
- SInt16 TString::CompareStringOrder(const TString& compareWith) const
- {
- return IUTextOrder(this->TextStart(), compareWith.TextStart(),
- this->StringLength(), compareWith.StringLength(),
- this->StringScript(), compareWith.StringScript(),
- this->StringLanguage(), compareWith.StringLanguage());
- }
-
- //----------------------------------------------------------------------------------------
- // TString::Equivalent:
- //----------------------------------------------------------------------------------------
- Boolean TString::Equivalent(const TString& compareWith) const
- {
- Boolean isEqual = false;
-
- isEqual = (this->CompareStringOrder(compareWith) == 0);
-
- return isEqual;
- } // TString::Equivalent
-
- //----------------------------------------------------------------------------------------
- // TString::Equal: case insensitive, diacritical sensitive
- //----------------------------------------------------------------------------------------
- Boolean TString::Equal(const TString& compareWith) const
- {
- return this->Equivalent(compareWith);
- } // TString::Equal
-
- //----------------------------------------------------------------------------------------
- // TString::ExactlyEqual: case sensitive, diacritical sensitive
- //----------------------------------------------------------------------------------------
- Boolean TString::ExactlyEqual(const TString& compareWith) const
- {
- return this->Equivalent(compareWith);
- } // TString::ExactlyEqual
-
- //----------------------------------------------------------------------------------------
- // TString::NearlyEqual: case insensitive, diacritical insensitive
- //----------------------------------------------------------------------------------------
- Boolean TString::NearlyEqual(const TString& compareWith) const
- {
- return this->Equivalent(compareWith);
- } // TString::NearlyEqual
-
- //----------------------------------------------------------------------------------------
- // TString::FindOffset:
- //----------------------------------------------------------------------------------------
- SInt32 TString::FindOffset(const TString& searchPattern) const
- {
- SInt32 foundStartIndex = kSubstringNotFound;
-
- if(searchPattern.StringLength() > 0)
- {
- //
- // Search through this string to see if we can find the
- // search pattern at any offset.
- //
- // Skip comparisons at byte offsets that are in the middle
- // of multi-byte characters.
- //
- UInt32 bytesToCheck = this->StringLength() - searchPattern.StringLength();
- UInt32 currentPosition = 0;
- while((currentPosition < bytesToCheck) && (foundStartIndex == kSubstringNotFound))
- {
- //
- // If thisCharType is smSingleByte or smFirstByte, then we want
- // to compare at this postion. If it is smLastByte or smMiddleByte,
- // then skip it.
- //
- // CharacterByteType requires System 7.1
- //
- SInt16 thisCharType = CharacterByteType((char*)this->TextStart(), currentPosition, this->StringScript());
- if((thisCharType == smFirstByte) || (thisCharType == smFirstByte))
- {
- TString subString((unsigned char*)(this->TextStart() + currentPosition), searchPattern.StringLength(), searchPattern.StringLength(), this->StringScript(), this->StringLanguage());
- if(subString.Equivalent(searchPattern))
- foundStartIndex = currentPosition;
- }
-
- ++currentPosition;
- }
- }
-
- return foundStartIndex;
- } // TString::Contains
-
- //----------------------------------------------------------------------------------------
- // TString::Contains:
- //----------------------------------------------------------------------------------------
- Boolean TString::Contains(const TString& searchPattern) const
- {
- return this->FindOffset(searchPattern) != kSubstringNotFound;
- } // TString::Contains
-
- //----------------------------------------------------------------------------------------
- // TString::Delete:
- //----------------------------------------------------------------------------------------
- void TString::Delete(UInt32 destStartIndex, UInt32 destEndIndex)
- {
- if((destStartIndex >= 0) && (destStartIndex < this->StringLength()) && (destEndIndex > destStartIndex))
- {
- UInt32 bytesToMove = this->StringLength() - destEndIndex;
-
- if(bytesToMove > 0)
- {
- CopyMemory(this->TextStart() + destEndIndex, this->TextStart() + destStartIndex, bytesToMove);
- this->SetLength(destStartIndex + bytesToMove);
- }
- else
- {
- this->SetLength(destStartIndex);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TString::ExpandToFit
- //----------------------------------------------------------------------------------------
- void TString::ExpandToFit(UInt32 spaceRequired)
- {
- if(fStorageAllocatedInHeap && (this->MaximumSizeInBytes() < spaceRequired))
- {
- //
- // Round up the size to the next even multiple of 'kStringAllocationChunk'
- //
- UInt32 newAllocationSize = ((((spaceRequired + kStringAllocationChunk - 1) / kStringAllocationChunk)) * kStringAllocationChunk);
- unsigned char* newStringStorage = new unsigned char[newAllocationSize];
-
- CopyMemory(&fStr[0], newStringStorage, this->SizeInBytes());
- delete fStr;
- fStr = newStringStorage;
- fMaximumSizeInBytes = newAllocationSize;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // TString::InsertAfter:
- //----------------------------------------------------------------------------------------
- Boolean TString::InsertAfter(UInt32 destStartIndex, const TString& replaceWith)
- {
- UInt32 bytesToInsert = replaceWith.StringLength();
- Boolean insertionFit = true;
-
- if((destStartIndex >= 0) && (bytesToInsert > 0))
- {
- //
- // Make room for the insert, if possible. If there
- // isn't enough space, then truncate
- //
- this->ExpandToFit(this->StringLength() + bytesToInsert);
- SInt32 overflowAmount = (this->StringLength() + bytesToInsert + 1) - this->MaximumSizeInBytes();
- if(overflowAmount > 0)
- {
- insertionFit = false;
- SInt32 newLength = this->StringLength() - overflowAmount;
- if(newLength < destStartIndex)
- newLength = destStartIndex;
- overflowAmount -= (this->StringLength() - newLength);
- this->SetLength(newLength);
- bytesToInsert -= overflowAmount;
- }
-
- if(bytesToInsert > 0)
- {
- //
- // Calculate how many bytes we need to copy after the
- // starting index in order to make room for the insertion.
- //
- if(destStartIndex > this->StringLength())
- destStartIndex = this->StringLength();
- UInt32 bytesToMove = this->StringLength() - destStartIndex;
-
- if(bytesToMove > 0)
- CopyMemory(this->TextStart() + destStartIndex, this->TextStart() + destStartIndex + bytesToInsert, bytesToMove);
- CopyMemory(replaceWith.TextStart(), this->TextStart() + destStartIndex, bytesToInsert);
-
- this->SetLength(this->StringLength() + bytesToInsert);
-
- //
- // Any time you replace some text in a string, the entire
- // script and language of the destination string takes
- // on the script and language of the inserted text.
- //
- // Such is the life of single-script strings. :<
- //
- fStringScript = replaceWith.StringScript();
- fStringLanguage = replaceWith.StringLanguage();
- }
- }
-
- return insertionFit;
- }
-
- //----------------------------------------------------------------------------------------
- // TString::Replace:
- //----------------------------------------------------------------------------------------
- void TString::Replace(UInt32 destStartIndex, UInt32 destEndIndex, const TString& replaceWith)
- {
- this->Delete(destStartIndex, destEndIndex);
- this->InsertAfter(destStartIndex, replaceWith);
- } // TString::Replace
-
- //----------------------------------------------------------------------------------------
- // TString::Append:
- //----------------------------------------------------------------------------------------
- void TString::Append(const TString& appendString)
- {
- this->InsertAfter(kStringEnd, appendString);
- } // TString::Append
-
- //----------------------------------------------------------------------------------------
- // TString::Prefix:
- //----------------------------------------------------------------------------------------
- void TString::Prefix(const TString& prefixString)
- {
- this->InsertAfter(kStringStart, prefixString);
- } // TString::Prefix
-
- //----------------------------------------------------------------------------------------
- // TString::ConvertToStr255
- //----------------------------------------------------------------------------------------
- void TString::ConvertToStr255(Str255 destination)
- {
- TString outputString(destination, 255);
-
- outputString = *this;
- }
-
- //========================================================================================
- // CLASS TStackBasedString
- //========================================================================================
-
- TStackBasedString::TStackBasedString(const TString& sourceStr) : TString(fStringStorage, kStackBasedStringStorageUnits * sizeof(unsigned char))
- {
- *this = sourceStr;
- }
-